<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      #div {
        width: 100px;
        height: 100px;
        background-color: red;
      }
    </style>
  </head>
  <body>
    <div id="div"></div>
  </body>
  <script>
    /*
                1.var和let const 的区别？
                相同点：都是定义一个变量，
               1.var是ES5语法，有变量提升。let和const是ES6语法，let和const是块级作用域，var是函数级作用域。
               2.var声明的变量可以重复声明，let和const声明的变量不能重复声明
               3.const定义的常量不能被修改，let定义的变量可以修改。


               2.typeof能判断那些类型？
                undefined，string,number,boolean,symbol,
                function
                object(typeof null返回object)

               3.列举强制类型转换和隐式类型转换
                强制类型转换：parseInt(),parseFloat(),Number(),String(),Boolean(),toString()
                隐式类型转换:if、逻辑运算、==、+拼接字符串


                4.手写深度比较，模拟lodash isEqual方法


                5.split()和join()的区别？
                split()方法通过指定分隔符将一个字符串分割成数组，join()方法通过指定分隔符将数组元素连接成字符串。
                区别：
                1.split()方法返回的是一个数组，join()方法返回的是一个字符串。


                6.数组的push pop shift unshift 分别做什么？
            //纯函数：1.不改变源数组，2.返回一个数组
            //纯函数：slice map filter reduce find findIndex every some indexOf lastIndexOf
                7.数组slice和splice的区别？
                8.[10,20,30].map(parseInt)返回结果是什么？
                    相当于
                    [10,20,30].map(function(item,index){
                        return parseInt(item，index);
                    })
            parseInt(string, radix)，其中：
            string 是要进行转换的字符串。
            1.对于 parseInt 第二个参数。从 2 到 36 的整数，表示进制的基数。
            2.如果超出这个范围，将返回 NaN。如果一个参数的开头数字大于进制数，将返回 NaN。
            3.如果第一个参数之后的数大于进制数，将忽略。
            4.如果radix参数为0，则radix将被设置为10。

        。
                9.ajax请求get和post的区别？
                get一般用于查询操作，post一般用于用户提交操作。
                get参数拼接在url上，post放在请求体内
                安全性：post易于防止CSRF攻击。



                10.函数call和apply的区别？


                11.事件代理（委托）是什么？


                12.闭包是什么，有什么特性，有什么负面影响？
                影响：变量会常住内存，得不到释放。闭包不要乱用

                13.如何阻止事件冒泡和默认行为？
                event.stopPropagation()
                event.preventDefault()
                14.查找、添加、删除、移动DOM节点的方法？

                15.如何减少DOM操作？
                1.缓存DOM查询结果
                2.多次插入DOM，合并到文档碎片中，一次性插入文档


                16解释jsonp原理，为何它不是真正的ajax?
                17.document load 和 ready 的区别？
                ready就是DOMContentLoaded事件。load是页面所有资源加载完毕。
                18.== 和 === 的区别？

                19.函数声明和函数表达式的区别？
                函数声明 function fn(){}
                let fn = function(){}
                js预解析时，会把函数声明提升到函数作用域的最前面，而函数表达式不会。表达式会把fn提到最前面。function(){}还在原地。
                20.new Object（）和Object.create（null）的区别？
                    {}等同于new Object(),原型Object.prototype。
                    Object.create(null)创建一个空对象，没有原型链。
                    Object.create({...})创建了一个对象，将这个对象的原型指向了传入的对象
                21.关于this的场景题

                22.手写字符串trim方法，保证浏览器兼容性
             String.prototype.trim = function() {
             return this.replace(/^\s+/g,'').replace(/\s+$/,'')
            }
            window.onerror = function (msg, source) {
             console.log(msg, source);
           };
                23.如何获取多个数字中的最大值？

                24.如何用JS实现继承?
                class继承
                prototype继承

                25.如何获取JS程序中的异常？
                    try{
                      todo
                    }catch(ex){
                    console.error(ex)
                    }finally{
                    todo
                    }

                26.什么是JSON?
            json是一种数据格式，本质是一段字符串
            json格式和JS对象结构一致，对JS语言更友好
            window.JSON是一个全局对象：JSON.stringify  JSON.parse

                27.获取当前页面url参数？
                1.传统方式，查找location.search，然后用字符串处理，比较麻烦。
                2.使用URLSearchParams，可以直接获取对象形式的查询参数。
                const p = new URLSearchParams(location.search);
                console.log(p.get("name"));
                28.手写数组flatern,考虑多层级？
                29.数组去重？
               29.substring()和substr()的区别？
                1.substring()方法类似于slice()方法，第一个参数是开始索引，第二个参数是结束索引，
                结束的这个索引截取不到。并返回一个新的字符串。
                2.substr()方法是字符串截取的方法，第一个参数是开始索引，第二个参数是截取的长度。并返回一个新的字符串。

                30.介绍一下RAFrequestAnimationFrame?
                1.想要动画流畅，更新频率要60帧/s,即16.67ms更新一次视图
                2.setTimeout要手动控制频率，而RAF浏览器会自动控制
                3.后台标签或隐藏iframe中，RAF会暂停，而setTimeout依然执行

                30.Object.assign()的用法？
               
                用于对象的合并，将多个对象的可枚举属性，复制到目标对象（target）中。
                第一个参数是目标对象，后面的参数是源对象。
                目标对象和源对象有同名属性，则后面的源对象属性会覆盖前面的属性。
                不是深拷贝。
                
            */
    let a = 10;
    var b = 20;
    var b = 30;
    let c = 30;
    c = 450;
    const d = 20;
    let s = Symbol("hello");
    console.log(typeof s); // number
    function isEqual(a, b) {
      if (a === b) {
        return true;
      } else if (typeof a !== typeof b) {
        return false;
      } else if (typeof a === "object" && a !== null) {
        if (Array.isArray(a)) {
          if (a.length !== b.length) {
            return false;
          }
          for (let i = 0; i < a.length; i++) {
            let res = isEqual(a[i], b[i]);
            if (!res) return false;
          }
          return true;
        } else {
          let aKeys = Object.keys(a);
          let bKeys = Object.keys(b);

          if (aKeys.length !== bKeys.length) {
            return false;
          }
          for (let i = 0; i < aKeys.length; i++) {
            if (!isEqual(a[aKeys[i]], b[bKeys[i]])) {
              return false;
            }
          }
          return true;
        }
      }
    }
    let a1 = {
      name: "10",
      age: 20,
      address: { city: "beijing", country: "china", cc: [1, 2, 3, [4, 5]] },
    };
    let a2 = {
      name: "10",
      age: 20,
      address: { city: "beijing", country: "china", cc: [1, 2, 3, [4, 5]] },
    };
    console.log(isEqual(a1, a2));
    let r1 = [1, 2, 3];
    let r2 = [4, 5, 6];
    let res = r1.concat(r2, [7], [90, 29]); // [1,2,3,4,5,6]
    console.log(res, "res", r1, r2);
    console.log(res.slice(0, 4));
    let r3 = res.forEach((item) => {
      item = item * 2;
    });
    console.log(r3, "r3", res);
    console.log(parseInt("322"));
    let res3 = [10, 10, 33].map(function (item, index) {
      return parseInt(item, index);
    });
    console.log(res3);
    console.log(parseInt("30", 4));
    //如果之后的数大于进制数，会忽略。

    let obj1 = { name: "zs", age: 18, sex: "male" };

    let obj2 = Object.create(obj1);

    console.log(obj2.__proto__ === obj1.prototype, "obj2");
    let str1 = "afdsf12";

    for (var i = 1; i <= 3; i++) {
      console.log(i, "i");
    }
    console.log(/^[a-zA-Z]\w{5,27}$/.test("fds252fds_fdsssssssssss"));
    /* 打印题1 */
    /*  let aa = 100;
        function test() {
          console.log(aa, "a1"); // 100 a1
          aa = 10;
          console.log(aa, "a2"); // 10 a2
        }
        test();
        console.log(aa, "a3"); // 10 a3 */
    /* 打印题2 */
    /*  let aa = 100;
        function test() {
          console.log(aa, "a1"); // undefined
          var aa = 10;
          console.log(aa, "a2"); // 10
        }
        test();
        console.log(aa, "a3"); // 100 */
    
    let str11 = " fds fds     ";
    str11 = str11.trim();
    console.log(str11, "s1");
    let n1 = 10;
    let n2 = 20;
    let n3 = 30;
    function getMaxNum() {
      let arr = Array.prototype.slice.call(arguments).flat(100);
      let max = 0;
      arr.forEach((item) => {
        if (item > max) {
          max = item;
        }
      });
      return max;
    }
    /*
    ?name=fdsage=23
    */
    /* 获取search参数 */
    function getParams() {
      let obj = {};
      let url = window.location.search.substr(1).split("&");

      url.forEach((item) => {
        let arr = item.split("=");
        obj[arr[0]] = arr[1];
      });
      return obj;
    }
    console.log(getParams());
    const p = new URLSearchParams(location.search);
    console.log(p.get("name"));
    function flatern(arr) {
      let res = [];
      arr.forEach((item) => {
        if (Array.isArray(item)) {
          res.push(...flatern(item));
        } else {
          res.push(item);
        }
      });
      return res;
    }
    console.log(
      flatern([
        1,
        5,
        6,
        7,
        3,
        53,
        53,
        2,
        634,
        [53, 53, [5353, 53, [35, 35, 11]]],
      ])
    );
    let arr4 = [1, 2, 4, 6, 5, 7, 2, 1, 5];
    console.log(arr4.indexOf(2), "indexof");
    function filterArr(arr) {
      let res = [];
      for (let i = 0; i < arr.length; i++) {
        if (res.indexOf(arr[i]) == -1) {
          res.push(arr[i]);
        }
      }
      return res;
    }
    console.log(filterArr(arr4));
    let set1 = new Set();
    set1.add(1);
    console.log(set1.add(3));
    console.log(set1);
    let res6 = set1.entries(set1);
    console.log(res6);
    let obj3 = { name: "zs", age: 18, sex: "male", c: { name: "zs1" } };
    let obj4 = Object.assign({ a: 5 }, { a: 10 }, obj3);
    console.log(obj3, obj4);
    let _div = document.getElementById("div");
    // function animate() {
    //   _div.style.width = _div.offsetWidth + 3 + "px";
    //   if (_div.offsetWidth < 1400) {
    //     requestAnimationFrame(animate);
    //   }
    // }
    function animate() {
      _div.style.width = _div.offsetWidth + 3 + "px";
      if (_div.offsetWidth < 1400) {
        setTimeout(animate, 16.67);
      }
    }
    animate();
  </script>
</html>
